package cn.itsource.ymcc.service.impl;

import cn.itsource.ymcc.client.SearchClient;
import cn.itsource.ymcc.doc.CourseDoc;
import cn.itsource.ymcc.domain.*;
import cn.itsource.ymcc.dto.CourseDto;
import cn.itsource.ymcc.mapper.*;
import cn.itsource.ymcc.result.JsonResult;
import cn.itsource.ymcc.service.ICourseService;
import cn.itsource.ymcc.util.AssertUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author whale.chen
 * @since 2023-02-27
 */
@Slf4j
@Service
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements ICourseService {

    @Autowired
    private TeacherMapper teacherMapper;
    @Autowired
    private CourseDetailMapper courseDetailMapper;
    @Autowired
    private CourseMarketMapper courseMarketMapper;
    @Autowired
    private CourseSummaryMapper courseSummaryMapper;
    @Autowired
    private CourseResourceMapper courseResourceMapper;
    @Autowired
    private CourseTypeMapper courseTypeMapper;
    @Autowired
    private SearchClient searchClient;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    /**
     * 新增课程
     *  课程主表
     *  课程详情表
     *  课程市场营销信息表
     *  课程统计信息表
     *  课程课件资源表
     *  课程与讲师的中间表
     * @param courseDto
     */
    @Transactional
    @Override
    public void save(CourseDto courseDto) {
        //1.保存课程主表信息
        Course course = courseDto.getCourse();
        //课程的讲师名称
        if(courseDto.getTeacharIds() != null && !courseDto.getTeacharIds().isEmpty()){
            List<Teacher> teachers = teacherMapper.selectBatchIds(courseDto.getTeacharIds());
            //获取讲师名称
            List<String> teacherNames = teachers.stream().map(t -> t.getName()).collect(Collectors.toList());
            course.setTeacherNames(String.join(",", teacherNames));
        }
        baseMapper.insert(course);

        //2.保存课程详情表
        CourseDetail courseDetail = courseDto.getCourseDetail();
        courseDetail.setId(course.getId());
        courseDetailMapper.insert(courseDetail);

        //3.保存课程市场营销信息表
        CourseMarket courseMarket = courseDto.getCourseMarket();
        courseMarket.setId(course.getId());
        courseMarketMapper.insert(courseMarket);

        //4.课程统计信息表
        CourseSummary courseSummary = new CourseSummary();
        courseSummary.setId(course.getId());
        courseSummaryMapper.insert(courseSummary);

        //5.课程课件资源表
        if(courseDto.getZipResources() != null && !courseDto.getZipResources().isEmpty()){
            for (String zipResource : courseDto.getZipResources()) {
                CourseResource courseResource = new CourseResource();
                courseResource.setCourseId(course.getId());
                courseResource.setResources(zipResource);
                courseResourceMapper.insert(courseResource);
            }
        }

        //6.课程与讲师的中间表：由于我们中间表是没有生成代码的，必须自己写【写在CourseMapper或者TeacherMapper中都行】
        if(courseDto.getTeacharIds() != null && !courseDto.getTeacharIds().isEmpty()){
            //批量保存
            baseMapper.insertBatchCourseTeacher(course.getId(), courseDto.getTeacharIds());
        }
    }

    /**
     * 修改课程
     *  课程主表信息
     *  课程详情信息
     *  课程市场营销信息
     *  课程的讲师：只能先通过课程id删除中间表数据，再重新添加
     *  课程的课件资源：只能先通过课程id删除课件资源表数数据，再重新添加
     * @param courseDto
     */
    @Transactional
    @Override
    public void updateById(CourseDto courseDto) {
        Course course = courseDto.getCourse();
        baseMapper.updateById(course);



    }

    /**
     * 课程编辑：回显数据【课程详情、课程市场营销、统计信息、课程所属类别、课程的讲师id集合、课程的资源集合】
     * @param courseId
     * @return
     */
    @Override
    public Map<String, Object> getDetailById(Long courseId) {
        Course course = baseMapper.selectById(courseId);
        CourseDetail courseDetail = courseDetailMapper.selectById(courseId);
        CourseMarket courseMarket = courseMarketMapper.selectById(courseId);
        CourseSummary courseSummary = courseSummaryMapper.selectById(courseId);
        CourseType courseType = courseTypeMapper.selectById(course.getCourseTypeId());
        List<Long> teacherIds = baseMapper.selectCourseTeacherIds(courseId);
        List<CourseResource> resourceList = courseResourceMapper.selectList(new QueryWrapper<CourseResource>().eq("course_id", courseId));

        Map<String,Object> map = new HashMap<>();
        map.put("courseDetail", courseDetail);
        map.put("courseMarket", courseMarket);
        map.put("courseSummary", courseSummary);
        map.put("courseType", courseType);
        map.put("teacherIds", teacherIds);
        map.put("resourceList", resourceList);

        return map;
    }

    /**
     * 课程发布上线
     * @param courseList
     * @return
     */
    @Transactional
    @Override
    public JsonResult onLineCourse(List<Course> courseList) {
        //1.校验数据：用户勾选的课程中不能包含已上线的课程
        //筛选出已上线的课程
        List<Course> courseOnlined = courseList.stream().filter(course -> course.getStatus() == 1).collect(Collectors.toList());
        AssertUtil.isTrue(courseOnlined == null || courseOnlined.isEmpty(), "对不起，您勾选的课程中包含了已上线的课程！");

        //2.修改状态：1）可以循环一个一个  2）可以写一个批量修改
        for (Course course : courseList) {
            course.setStatus(1);
            course.setOnlineTime(new Date());
            baseMapper.updateById(course);
        }

        //3.openfeign调用全文检索服务接口
        List<CourseDoc> courseDocs = courseList.stream()
                .map(course -> course2Doc(course)).collect(Collectors.toList());
        JsonResult jsonResult = searchClient.saveBatch(courseDocs);
        AssertUtil.isTrue(jsonResult.getSuccess(), jsonResult.getMessage());

        /**
         * 4.消息推送【锦上添花的功能，不重要，允许消息消息丢失，起到一个推广的作用】
         * 1）三种消息：邮件、短信、站内信
         * 2）消息内容：亲爱的Xxx用户，你好！您关注的XXXX课程发布上线了，请点击xxxxxx链接获取最新资讯。
         * 3）发给谁？推送给关注过同类型课程的用户
         *  首先根据当前上线的课程的所属类别查询同类别的课程id；
         *  然后根据这些课程id查询收藏记录表，得到用户id；
         *  最后openfeign：根据这些用户id查询用户表，得到他们的手机号和邮箱；
         */
//        MessageDto messageDto = new MessageDto();
//        messageDto.setTitle("课程发布");
//        List<String> courseNames = courseList.stream()
//                .map(course -> course.getName()).collect(Collectors.toList());
//        messageDto.setContent("亲爱的用户您好，最新课程 <a href='测试'> "+String.join("，", courseNames)+" </a> 发布啦，点击课程了解详情");
//        messageDto.setSmsDtoList(Arrays.asList(
//                new MessageDto.SmsDto(1L, "18996157300", null),
//                new MessageDto.SmsDto(2L, "18996157301", null),
//                new MessageDto.SmsDto(3L, "18996157302", null)
//        ));
//        messageDto.setEmailDtoList(Arrays.asList(
//                new MessageDto.EmailDto(1L, "9578987@qq.com", null),
//                new MessageDto.EmailDto(2L, "9578988@qq.com", null),
//                new MessageDto.EmailDto(3L, "9578989@qq.com", null)
//        ));
//        messageDto.setStationDtoList(Arrays.asList(
//                new MessageDto.StationDto(1L, "系统消息"),
//                new MessageDto.StationDto(2L, "系统消息"),
//                new MessageDto.StationDto(3L, "系统消息")
//        ));
//        Message<String> message = MessageBuilder.withPayload(JSON.toJSONString(messageDto)).build();
//        //发短信
//        rocketMQTemplate.sendOneWay(
//                Cons.Message.TOPIC_MESSAGE+":"+Cons.Message.TAGS_MESSAGE_SMS,
//                message
//        );
//        //发邮件
//        rocketMQTemplate.sendOneWay(
//                Cons.Message.TOPIC_MESSAGE+":"+Cons.Message.TAGS_MESSAGE_EMAIL,
//                message
//        );
//        //发站内信
//        rocketMQTemplate.sendOneWay(
//                Cons.Message.TOPIC_MESSAGE+":"+Cons.Message.TAGS_MESSAGE_STATION,
//                message
//        );
        return JsonResult.me();
    }

    /**
     * 给我一个Course对象，返回你一个CourseDoc对象
     * @param course
     * @return
     */
    private CourseDoc course2Doc(Course course) {
        CourseDoc courseDoc = new CourseDoc();
        BeanUtils.copyProperties(course, courseDoc);
        //查询课程类别
        CourseType courseType = courseTypeMapper.selectById(course.getCourseTypeId());
        courseDoc.setCourseTypeName(courseType.getName());
        //Date转时间戳
        courseDoc.setStartTime(course.getStartTime().getTime());
        courseDoc.setEndTime(course.getEndTime().getTime());
        courseDoc.setOnlineTime(System.currentTimeMillis());

        //课程详情
        CourseDetail courseDetail = courseDetailMapper.selectById(course.getId());
        BeanUtils.copyProperties(courseDetail, courseDoc);

        //课程市场营销信息
        CourseMarket courseMarket = courseMarketMapper.selectById(course.getId());
        BeanUtils.copyProperties(courseMarket, courseDoc);
        courseDoc.setPrice(courseMarket.getPrice().doubleValue());
        courseDoc.setPriceOld(courseMarket.getPriceOld().doubleValue());

        //课程统计信息
        CourseSummary courseSummary = courseSummaryMapper.selectById(course.getId());
        BeanUtils.copyProperties(courseSummary, courseDoc);

        return courseDoc;
    }
}